
import { httpPost, fileUploader, filePost } from './http.js'
import CryptoJS from './crypto-js.js'

const Host = 'https://raasr.xfyun.cn/api/'
const C_upload = 'http://39.100.22.224/xunfei/upload'
const {atob} = require('./atob.js')
const API = {
	prepare: Host+'prepare',
	c_upload: C_upload,
	upload: Host+'upload',
	merge: Host+'merge',
	get_progress: Host+'getProgress',
	get_result: Host+'getResult'
}


class SliceIdGenerator {
    constructor() {
        this.__ch = this.randomString(10)
    }
	
	randomString(len) {
		len = len || 32;
		var $chars = 'abcdefhijkmnprstwxyz';
		var maxPos = $chars.length;
		var pwd = '';
		for (let i = 0; i < len; i++) {
			pwd += $chars.charAt(Math.floor(Math.random() * maxPos));
		}
		return pwd;
	}

    getNextSliceId() {
        let ch = this.__ch
        let i = ch.length - 1
        while (i >= 0) {
            let ci = ch[i]
            if (ci !== 'z') {
                ch = ch.slice(0, i) + String.fromCharCode(ci.charCodeAt(0) + 1) + ch.slice(i + 1)
                break
            } else {
                ch = ch.slice(0, i) + 'a' + ch.slice(i + 1)
                i--
            }
        }
        this.__ch = ch
        return this.__ch
    }
}

export default class XunFeiSpeechAPI {
	
	constructor(appid, secret_key, upload_file_path) {
	    this.appid = appid
		this.secret_key = secret_key
		this.upload_file_path = upload_file_path
		this.slice_generator = new SliceIdGenerator()
	}
	
	base64ToArrayBuffer(base64) {
	  var binaryString = atob(base64)
	  var len = binaryString.length
	  var bytes = new Uint8Array(len)
	  for (var i = 0; i < len; i++) {
		bytes[i] = binaryString.charCodeAt(i)
	  }
	  return bytes.buffer
	}
	
	get_signa(ts) {
	    const md5 = CryptoJS.MD5(this.appid + ts).toString()
	    const sha1 = CryptoJS.HmacSHA1(md5, this.secret_key)
	    const signa = CryptoJS.enc.Base64.stringify(sha1)
	    return signa
	}
	
	
	
	async get_file_info() {
		const self = this
		
		// #ifdef APP-PLUS
		let name = '录音.mp3'
		// #endif
		
		// #ifndef APP-PLUS
		let name = '录音.m4a'
		// #endif
		
		let res = await uni.getFileInfo({
			filePath: this.upload_file_path,
		})
		const size = res[1].size
		
		// #ifdef APP-PLUS
		// 请求本地系统文件对象 plus.io.PRIVATE_WWW：应用运行资源目录常量
		const fileError = (code) => {
			return (e) => {
				uni.showToast({
					title: code+'-文件系统调取失败：'+JSON.stringify(e.message),
					icon: 'none'
				})
			}
		}
		const fileReaderPromise = (file_path) => {
			return new Promise((resolve, reject) => {
				plus.io.requestFileSystem(plus.io.PRIVATE_WWW, function(entry){
					// entry.root是根目录操作对象DirectoryEntry
					entry.root.getFile(self.upload_file_path, {create:false} , function(fileEntry){
						fileEntry.file(function(file){
							let fileReader = new plus.io.FileReader();
							fileReader.readAsDataURL(file, 'utf-8');
							fileReader.onloadend = function(evt) {
								resolve(evt.target.result)
							}
						});
					}, fileError(2));
				}, fileError(3));
			})
		}
		self.res = await fileReaderPromise(this.upload_file_path)
		// #endif
		
		// #ifndef APP-PLUS
		const fileManager = uni.getFileSystemManager()
		let base64
		self.res = fileManager.readFileSync(this.upload_file_path, 'base64')
		// #endif
		
		return {
			size,
			name,
			content: self.res
		}
	}
	
	async get_params(api, task_id) {
		const app_id = this.appid
		const secret_key = this.secret_key
		const upload_file_path = this.upload_file_path
		const ts = parseInt(new Date().getTime() / 1000)
		const signa = this.get_signa(ts)
		const fileInfo = await this.get_file_info()
		const file_len = fileInfo.size
		const file_name = fileInfo.name

		const content = this.res || fileInfo.content
		let params = {
			app_id,
			ts,
			signa
		}
		const api_params_mapping = () => {
			return {
				'https://raasr.xfyun.cn/api/prepare': {
					file_len, file_name, slice_num: 1
				},
				'https://raasr.xfyun.cn/api/upload': {
					task_id, 
					slice_id: this.slice_generator.getNextSliceId(),
					content: content
				},
				'http://39.100.22.224/xunfei/upload': {
					task_id,
					slice_id: this.slice_generator.getNextSliceId(),
					content: content
				},
				'https://raasr.xfyun.cn/api/merge': {
					task_id, file_name
				},
				'https://raasr.xfyun.cn/api/getProgress': {
					task_id
				},
				'https://raasr.xfyun.cn/api/getResult': {
					task_id
				}
			}[api]
		}
		
		return Object.assign(params, api_params_mapping())
	}
	
	async request(api, task_id) {
		const [err, res] = await httpPost(api, 
			await this.get_params(api, task_id))
		if(res && res.data.ok === 0) {
			return res
		}
		throw Error(api+'请求失败'+JSON.stringify(res || err))
	}
	
	async pre_request() {
		return await this.request(API.prepare)
	}
	
	async upload_request(task_id) {
		const res = await httpPost(API.upload,
			await this.get_params(API.upload, task_id))
		return res
	}
	
	async merge_request(task_id) {
		return await this.request(API.merge, task_id)
	}
	
	get_progress_request(task_id) {
        let self = this
        return new Promise((resolve, reject) => {
            function sleep(time) {
                return new Promise((resolve) => {
                    setTimeout(resolve, time)
                });
            }
            async function loopGetProgress() {
				try {
					let res = await self.request(API.get_progress, task_id)
					let data = JSON.parse(res.data.data)
					let taskStatus = data.status
					if (taskStatus === 9) {
						resolve()
					} else {
						sleep(1000).then(() => loopGetProgress())
					}
				} catch(e) {
					const res = JSON.parse(e.message.split('请求失败')[1])
					if(res.data.ok === -1){
						uni.showToast({
							title: res.data.failed,
							icon: 'none'
						})
						return
					}
					sleep(1000).then(() => loopGetProgress())
				}
            }
			
			loopGetProgress()
			
        })
    }
	
	async get_result_request(task_id) {
		return await this.request(API.get_result, task_id)
	}
	
	async requests() {
		try {
			const pre_request_data =  await this.pre_request()
			const task_id = pre_request_data.data.data
			await this.upload_request(task_id)
			await this.merge_request(task_id)
			await this.get_progress_request(task_id) // flag 判断音频是否为空
			return await this.get_result_request(task_id)
		} catch(e) {
			return {
				status: -1,
				error: e
			}
		}
	}
	
	
	
}


